package com.ruoyi.WELD.service.impl;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.ruoyi.WELD.domain.BaseWeld;
import com.ruoyi.WELD.domain.Weld;
import com.ruoyi.WELD.domain.Welding;
import com.ruoyi.WELD.mapper.WeldMapper;
import com.ruoyi.WELD.mapper.WeldingMapper;
import com.ruoyi.WELD.service.IWeldingService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Stream;
import com.alibaba.excel.write.metadata.fill.FillConfig;

@Service
@RequiredArgsConstructor   // Lombok 会为所有 final 字段生成构造器
public class WeldingServiceImpl implements IWeldingService {
    private static final Logger log = LoggerFactory.getLogger(WeldingServiceImpl.class);
    private final WeldingMapper weldingMapper;
    private final WeldMapper weldMapper;

    @Override
    public List<Welding> selectWeldingList(Welding welding) {
        return weldingMapper.selectWeldingList(welding);
    }

    @Override
    public Welding selectWeldingById(Long id) {
        return weldingMapper.selectWeldingById(id);
    }

    @Override
    public int insertWelding(Welding welding) {
        return weldingMapper.insertWelding(welding);
    }

    @Override
    public int updateWelding(Welding welding) {
        return weldingMapper.updateWelding(welding);
    }

    @Override
    public int deleteWeldingById(Long id) {
        return weldingMapper.deleteWeldingById(id);
    }

    @Override
    public int deleteWeldingByIds(Long[] ids) {
        return weldingMapper.deleteWeldingByIds(ids);
    }

    @Override
    public void ClearWelding() {
        weldingMapper.ClearWelding();
    }

    @Override
    public List<Welding> selectWeldingByIds(Long[] ids) {
        return weldingMapper.selectWeldingByIds(ids);
    }

    @SneakyThrows
    @Override
    public void exportByTemplate1(List<Welding> list,HttpServletResponse response) {
        int i=1;
        for (Welding welding:list){
            String sjNumber = welding.getSjNumber();
            String[] parts =sjNumber.split("-");
            if (parts.length>1){
                welding.setSjNumber(parts[0]);
                welding.setElectrodeForm(parts[1]);
            }
            welding.setId(i);
            i++;
        }
        exportExcel(list,response,"templates.excel/MB2000-R1.xlsx",null);
    }

    @SneakyThrows
    @Override
    public void exportByTemplate2(List<Welding> list, HttpServletResponse response) {
        exportExcel(list,response,"templates.excel/商科参数模板.xlsx",null);
    }

    @SneakyThrows
    @Override
    public void exportByTemplate3(List<Welding> list, HttpServletResponse response) {
        // 填充固定值
        List<Map<String, Object>> fixedValues = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> Values = new HashMap<>();
            // 假设固定值需要填充到占位符 {{fixedValue}}
//            Values.put("fixedValue", 1);
            Values.put("index", i + 1);
            fixedValues.add(Values);
        }
     exportExcel(list,response,"templates.excel/点焊专项验证报告+验证记录+问题清单.xlsx",fixedValues);
    }

    private void exportExcel(List<Welding> list, HttpServletResponse response,String templatePath, List<Map<String, Object>>fixedMap)throws Exception{

        // 文件模板输入流，将 excel 模板放到 resources 目录下
        InputStream templateFile = new ClassPathResource(templatePath).getInputStream();
        try(ServletOutputStream out = response.getOutputStream();
            ExcelWriter writer = EasyExcel.write(out)
                                          .withTemplate(templateFile)
                                          .build()){

            WriteSheet sheet = EasyExcel.writerSheet().build();
            FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();
            // 填充列表占位符
            writer.fill(list, fillConfig, sheet);

            if (fixedMap != null && !fixedMap.isEmpty()){
                writer.fill(fixedMap, fillConfig, sheet);
            }
        }
    }


    @Override
    public String GenerateUpdate(Welding welding1,Weld weld) {
        List<Welding> weldingList = weldingMapper.selectWeldingList(welding1);
        List<Weld> weldList = weldMapper.selectWeldList(weld);
        if (StringUtils.isNull(weldingList) || weldingList.isEmpty()) {
            throw new ServiceException("数据未选或者为0");
        }
        for (Welding welding : weldingList) {
            String Material3 = welding.getMaterial3();
            String Material4 = welding.getMaterial4();

            String result1 =canonKey(welding);
            Double mt = sum(welding);
            for (Weld w : weldList) {
                String W1 = canonKey(w);
                Double mt1=sum(w);
                if (result1.equals(W1)&& Math.abs(mt - mt1) <= 0.2 ) {
                    if (Material3 == null || Material3.isEmpty()) {
                        if (thicknessMatch(welding,w,new int []{0,1},0.1) ||
                            thicknessMatch(welding,w,new int []{1,0},0.1)){
                            updateWelding1(welding, w);
                            weldingMapper.updateWelding(welding);
                            break;
                        }
                    }else if (Material4 == null || Material4.isEmpty()) {
                        if (thicknessMatch(welding,w,new int []{0,1,2},0.1) ||
                            thicknessMatch(welding,w,new int []{2,1,0},0.1)){
                            updateWelding1(welding, w);
                            weldingMapper.updateWelding(welding);
                            break;
                        }
                    }else {
                        if (thicknessMatch(welding,w,new int []{0,1,2,3},0.1) ||
                            thicknessMatch(welding,w,new int []{3,2,1,0},0.1)){
                            updateWelding1(welding, w);
                            weldingMapper.updateWelding(welding);
                            break;
                        }
                    }
                }
            }
        }
        StringBuilder successMsg = new StringBuilder();
        successMsg.insert(0, "恭喜您");
        return successMsg.toString();
    }
    public void updateWelding1(Welding welding, Weld weld) {
        welding.setStress(weld.getStress());
        welding.setPreloadingTime(weld.getPreloadingTime());
        welding.setPressurizationTime(weld.getPressurizationTime());   // 新增
        welding.setPreheatingMethod(weld.getPreheatingMethod());       // 新增
        welding.setPreheatingTime(weld.getPreheatingTime());
        welding.setPreheatingCurrent(weld.getPreheatingCurrent());
        welding.setCoolingTime(weld.getCoolingTime());
        welding.setWeldingMethod(weld.getWeldingMethod());             // 新增
        welding.setIncreaseDecrease(weld.getIncreaseDecrease());       // 新增
        welding.setIncrementalTime(weld.getIncrementalTime());
        welding.setStartingCurrent(weld.getStartingCurrent());
        welding.setWeldingTime(weld.getWeldingTime());
        welding.setWeldingCurrent(weld.getWeldingCurrent());
        welding.setCoolingTime1(weld.getCoolingTime1());
        welding.setDeclineTime(weld.getDeclineTime());
        welding.setTerminationCurrent(weld.getTerminationCurrent());
        welding.setPulseFrequency(weld.getPulseFrequency());
        welding.setCoolingTime2(weld.getCoolingTime2());
        welding.setTemperingMethod(weld.getTemperingMethod());         // 新增
        welding.setTemperingTime(weld.getTemperingTime());
        welding.setTemperingCurrent(weld.getTemperingCurrent());
        welding.setHoldTime(weld.getHoldTime());
        welding.setParametricForm(weld.getParametricForm());
    }
    private boolean isClose(Double value1, Double value2, double tolerance) {
        if (value1 == null) value1 = 0.0;
        if (value2 == null) value2 = 0.0;
        return Math.abs(value1 - value2) <= tolerance;
    }
   //判断材质厚度是否符合
   private boolean thicknessMatch(Welding src, Weld target, int[] idx, double tol) {
       Double[] s = {
               src.getMaterialThickness1(),
               src.getMaterialThickness2(),
               src.getMaterialThickness3(),
               src.getMaterialThickness4()
       };
       Double[] t = {
               target.getMaterialThickness1(),
               target.getMaterialThickness2(),
               target.getMaterialThickness3(),
               target.getMaterialThickness4()
       };
       for (int i = 0; i < idx.length; i++) {
           if (!isClose(s[idx[i]], t[i], tol)) return false;
       }
       return true;
   }
    public static double sum(BaseWeld m) {
        return Stream.of(m.getMaterialThickness1(),
                        m.getMaterialThickness2(),
                        m.getMaterialThickness3(),
                        m.getMaterialThickness4())
                .mapToDouble(v -> v == null ? 0.0 : v)
                .sum();
    }
    private static String canonKey(BaseWeld w) {
        List<String> segs = new ArrayList<>(7);
        segs.add( val(w.getMaterial1()));
        segs.add( val(w.getMaterial2()));
        segs.add( val(w.getMaterial3()));
        segs.add( val(w.getMaterial4()));
        segs.add( val(w.getGumming1()));
        segs.add( val(w.getGumming2()));
        segs.add( val(w.getGumming3()));

        //不参与逆序的段
        List<String> fixSegs = Arrays.asList(val(w.getParametricForm()), val(w.getElectrodeForm()));

        List<String> fwd = new ArrayList<>(segs);
        List<String> rev = new ArrayList<>(segs);
        Collections.reverse(rev);//取反

        List<String> 代表 = fwd;
        if (rev.toString().compareTo(fwd.toString()) < 0) {   // 简单比较，够用
            代表 = rev;
        }
        List<String> all = new ArrayList<>(代表);
        all.addAll(fixSegs);
        return String.join("||", all);
    }
    // 把 null 转成字符串 ""
    private static String val(Object o) {
        return o == null ? "" : o.toString();
    }

    @Override
    public String importWelding(List<Welding> weldingList, Boolean isUpdateSupport) {
        if (StringUtils.isNull(weldingList) || weldingList.isEmpty()) {
            throw new ServiceException("导入数据不能为空！");
        }
        weldingList.forEach(this::stripSlash);
        int total = weldingList.size();
        try {
            weldingMapper.insertBatch(weldingList);
        }catch (Exception e){
           return insertOneByOne(weldingList);
        }
           return "数据批量导入成功！共："+total+"条";
    }
    private String insertOneByOne(List<Welding> weldingList){
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (Welding welding : weldingList) {
            try {
                weldingMapper.insertWelding(welding);
                successNum++;
                successMsg.append("<br/>" )
                          .append( successNum)
                          .append("、数据Welding ")
                          .append(" 导入成功");

            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>" )
                          .append(failureNum)
                          .append("、数据Welding ")
                          .append(" 导入失败");
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "数据逐条导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "数据逐条导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }
    private void stripSlash(Welding welding) {
        Field[] fields = welding.getClass().getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            try {
                if (f.getType() == String.class) {
                    String old = (String) f.get(welding);
                    if (old != null) {
                        String cleaned = old.replace("\\", "")
                                .replace("＼", "")
                                .replace("#N/A","");
                        f.set(welding, cleaned);
                    }
                }
            } catch (IllegalAccessException ignored) {
                // 忽略无法访问的字段
            }
        }
    }
}
